﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TGB.Core.Infrastructure;
using TGBTech.Core.Models.ChungTu;
using TGBTech.Core.Models.Models.BaoCao;
using TGBTech.Core.Models.Models.BaoCao.CanDoiKeToanModel;
using TGBTech.Core.Models.Models.DanhMuc;

namespace TGBTech.Core.Models.Services
{
    public class CanDoiKeToanService
    {
        public static char SYMBOL_SEPARATE = '.';
        public static String LOAIBAOCAO_CDKT = "CanDoiKeToan";
        public static String LOAIBAOCAO_KQKD = "KetQuaKinhDoanh";
        public static String LOAIBAOCAO_LCTT = "LuuChuyenTienTe";

        public CanDoiKetoan createCanDoiKeToan(String loaibaocao, DateTime ngaybatdau, DateTime ngayketthuc)
        {
            //check valid date
            if (!this._checkValidInput(ngaybatdau, ngayketthuc))
            {
                return null;
            }
            //init dbcontext
            using (var dbcontext = new TGBTechDb())
            {
                //get list taikhoanCDKT
                var listCDKT = (from e in dbcontext.TaiKhoanCDKT
                                where e.LoaiBaoCao == loaibaocao
                                select e).ToList();
                //check valid listCDKT
                if (listCDKT != null && listCDKT.Count <= 0)
                {
                    return null;
                }
                //init candoiketoan
                CanDoiKetoan candoiketoan = this._createCanDoiKeToan(ngaybatdau, ngayketthuc);
                //add list to ListModel
                _initCDKTListModel(ref candoiketoan, listCDKT);
                //query for valid data
                var validData = dbcontext.Data.ToList();
                //query for daunam value
                var queryDauNam = (from e in validData
                                   where e.NgayCT < ngaybatdau
                                   select e).ToList();
                _calculateCDKT(ref candoiketoan, true, queryDauNam);
                //query for trongnam value
                var queryTrongNam = (from e in validData
                                     where e.NgayCT >= ngaybatdau && e.NgayCT <= ngayketthuc
                                     select e).ToList();
                _calculateCDKT(ref candoiketoan, false, queryTrongNam);

                return candoiketoan;
            }
            
        }

        //calulate CDKT values
        private void _calculateCDKT(ref CanDoiKetoan candoiketoan, bool isDauNam, List<Data> listData)
        {
            CanDoiKeToanModel item;
            foreach (var model in candoiketoan.ListModel)
            { 
                item = model;
                _calculateCDKTRecus(ref item, isDauNam, listData);
            }
        }

        //calculate CDKT recus
        private void _calculateCDKTRecus(ref CanDoiKeToanModel model, bool isDaNam, List<Data> listData)
        {
            //if child
            if (model.TaiKhoanCon == null)
            {
                _calculateCDKTModel(ref model, isDaNam, listData);
            }
            else
            {
                CanDoiKeToanModel item;
                //loop to calculate child model
                for (int i = 0; i < model.TaiKhoanCon.Count; i++)
                {
                    item = model.TaiKhoanCon[i];
                    _calculateCDKTRecus(ref item, isDaNam, listData);
                }
            }
        }

        //caculate CDKTModel
        private void _calculateCDKTModel(ref CanDoiKeToanModel model, bool isDauNam, List<Data> listData)
        {
            String[] matks = model.TaiKhoanCDKT.MaTK.Split(SYMBOL_SEPARATE);
            Decimal sum = 0;
            Decimal sumOfCo = 0;
            Decimal sumOfNo = 0;
            foreach (var matk in matks)
            {
                sumOfCo += (from e in listData
                            where e.TaiKhoanCoId.StartsWith(matk)
                            select e.SoTien).ToList().Sum();
                sumOfNo += (from e in listData
                            where e.TaiKhoanNoId.StartsWith(matk)
                            select e.SoTien).ToList().Sum();
            }
            sum = sumOfNo - sumOfCo;
            if (sum < 0)
            {
                sum = -sum;
            }
            if (isDauNam)
            {
                model.SoDauNam = sum;
            }
            else
            {
                model.SoTrongNam = sum;
            }
        }

        //init CDKTListModel, init with child models in each model
        private void _initCDKTListModel(ref CanDoiKetoan candoiketoan, List<TaiKhoanCDKT> listCDKT)
        {
            CanDoiKeToanModel model;
            foreach (var cdkt in listCDKT)
            {
                model = new CanDoiKeToanModel();
                model.TaiKhoanCDKT = cdkt;
                candoiketoan.ListModel.Add(model);
            }
            //init child cdkt
            List<CanDoiKeToanModel> listModel;
            foreach (var cdkt in candoiketoan.ListModel)
            {
                //if there are no child in cdkt
                if (cdkt.TaiKhoanCDKT.TaiKhoanCon == null || cdkt.TaiKhoanCDKT.TaiKhoanCon == "")
                {
                    listModel = null;
                }
                else
                {
                    listModel = (from e in candoiketoan.ListModel
                                 where cdkt.TaiKhoanCDKT.TaiKhoanCon.Contains(e.TaiKhoanCDKT.MaSo)
                                 select e).ToList();
                }
                cdkt.TaiKhoanCon = listModel;
            }
        }

        //check valid input
        private bool _checkValidInput(DateTime ngaybatdau, DateTime ngayketthuc)
        {
            return !(ngaybatdau == null || ngayketthuc == null || ngaybatdau > ngayketthuc);
        }
        //init candoiketoan
        private CanDoiKetoan _createCanDoiKeToan(DateTime ngaybatdau, DateTime ngayketthuc)
        {
            //init candoikettoan
            CanDoiKetoan candoiketoan = new CanDoiKetoan();
            candoiketoan.ListModel = new List<CanDoiKeToanModel>();
            candoiketoan.NgayBatDau = ngaybatdau;
            candoiketoan.NgayKetThuc = ngayketthuc;
            return candoiketoan;
        }
    }
}
